import { AppError, NetworkError, ConfigError, AIServiceError } from './errors';
import { LogManager } from '../services/logManager';

export interface RetryConfig {
  maxRetries: number;
  baseDelay: number;
  maxDelay: number;
  backoffFactor: number;
}

export class ErrorHandler {
  private static defaultRetryConfig: RetryConfig = {
    maxRetries: 3,
    baseDelay: 1000,
    maxDelay: 10000,
    backoffFactor: 2
  };

  static async withRetry<T>(
    operation: () => Promise<T>,
    config: Partial<RetryConfig> = {}
  ): Promise<T> {
    const retryConfig = { ...this.defaultRetryConfig, ...config };
    let lastError: Error;

    for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
      try {
        return await operation();
      } catch (error) {
        lastError = error instanceof Error ? error : new Error(String(error));
        
        // 如果不是可恢复的错误，立即抛出
        if (error instanceof AppError && !error.recoverable) {
          throw error;
        }

        // 如果是最后一次尝试，抛出错误
        if (attempt === retryConfig.maxRetries) {
          break;
        }

        // 计算延迟时间
        const delay = Math.min(
          retryConfig.baseDelay * Math.pow(retryConfig.backoffFactor, attempt),
          retryConfig.maxDelay
        );

        console.warn(`操作失败，${delay}ms后重试 (${attempt + 1}/${retryConfig.maxRetries}):`, lastError.message);
        
        // 使用日志系统记录重试信息
        try {
          const logManager = LogManager.getInstance();
          logManager.warn('ErrorHandler', `操作重试 (${attempt + 1}/${retryConfig.maxRetries})`, {
            error: lastError.message,
            delay,
            attempt: attempt + 1,
            maxRetries: retryConfig.maxRetries
          });
        } catch {
          // 如果日志系统不可用，保持原有的console输出
        }
        await this.sleep(delay);
      }
    }

    throw this.enhanceError(lastError!);
  }

  static enhanceError(error: Error): AppError {
    if (error instanceof AppError) {
      return error;
    }

    // 网络相关错误
    if (error.message.includes('network') || 
        error.message.includes('timeout') ||
        error.message.includes('ECONNREFUSED') ||
        error.message.includes('ENOTFOUND')) {
      return new NetworkError(error.message);
    }

    // 配置相关错误
    if (error.message.includes('config') || 
        error.message.includes('JSON') ||
        error.message.includes('parse')) {
      return new ConfigError(error.message);
    }

    // AI服务相关错误
    if (error.message.includes('API') || 
        error.message.includes('model') ||
        error.message.includes('token')) {
      return new AIServiceError(error.message);
    }

    // 默认为通用应用错误
    return new AppError(error.message, 'UNKNOWN_ERROR', true);
  }

  static getErrorMessage(error: unknown): string {
    if (error instanceof AppError) {
      return error.message;
    }
    
    if (error instanceof Error) {
      return error.message;
    }
    
    return String(error);
  }

  static shouldRetry(error: unknown): boolean {
    if (error instanceof AppError) {
      return error.recoverable;
    }
    
    // 默认认为其他错误可以重试
    return true;
  }

  static logError(error: unknown, context: string = 'Unknown'): void {
    const timestamp = new Date().toISOString();
    const errorMessage = this.getErrorMessage(error);
    
    // 尝试使用日志系统
    try {
      const logManager = LogManager.getInstance();
      logManager.error(context, errorMessage, error instanceof Error ? error : new Error(String(error)));
    } catch {
      // 如果日志系统不可用，则回退到控制台输出
      console.error(`[${timestamp}] ${context}: ${errorMessage}`);
      
      if (error instanceof Error && error.stack) {
        console.error(error.stack);
      }
    }
  }

  static createUserFriendlyMessage(error: unknown): string {
    if (error instanceof NetworkError) {
      return '网络连接失败，请检查网络设置后重试';
    }
    
    if (error instanceof ConfigError) {
      return '配置文件有误，请检查 settings/app.json 文件';
    }
    
    if (error instanceof AIServiceError) {
      return 'AI 服务暂时不可用，请稍后重试';
    }
    
    if (error instanceof AppError) {
      return error.message;
    }
    
    return '发生未知错误，请重试';
  }

  private static sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// 全局错误处理器
export function setupGlobalErrorHandlers(): void {
  // 处理未捕获的 Promise 异常
  process.on('unhandledRejection', (reason, promise) => {
    ErrorHandler.logError(reason, 'UnhandledRejection');
    
    // 使用日志系统记录详细信息
    try {
      const logManager = LogManager.getInstance();
      logManager.error('GlobalErrorHandler', '未处理的 Promise 异常', {
        reason: reason instanceof Error ? {
          name: reason.name,
          message: reason.message,
          stack: reason.stack
        } : reason,
        promise: promise.toString()
      });
    } catch {
      console.error('未处理的 Promise 异常:', reason);
    }
  });

  // 处理未捕获的异常
  process.on('uncaughtException', (error) => {
    ErrorHandler.logError(error, 'UncaughtException');
    
    // 使用日志系统记录详细信息
    try {
      const logManager = LogManager.getInstance();
      logManager.error('GlobalErrorHandler', '未捕获的异常', {
        name: error.name,
        message: error.message,
        stack: error.stack
      });
      
      // 给日志系统一点时间写入日志
      setTimeout(() => {
        process.exit(1);
      }, 100);
    } catch {
      console.error('未捕获的异常:', error);
      process.exit(1);
    }
  });

  // 处理进程退出
  process.on('SIGINT', () => {
    try {
      const logManager = LogManager.getInstance();
      logManager.info('GlobalErrorHandler', '收到 SIGINT 信号，正在关闭应用');
      
      // 给日志系统时间关闭
      setTimeout(async () => {
        try {
          await logManager.shutdown();
        } catch (error) {
          console.error('日志系统关闭失败:', error);
        }
        console.log('\n收到退出信号，正在清理...');
        process.exit(0);
      }, 100);
    } catch {
      console.log('\n收到退出信号，正在清理...');
      process.exit(0);
    }
  });

  process.on('SIGTERM', () => {
    try {
      const logManager = LogManager.getInstance();
      logManager.info('GlobalErrorHandler', '收到 SIGTERM 信号，正在关闭应用');
      
      // 给日志系统时间关闭
      setTimeout(async () => {
        try {
          await logManager.shutdown();
        } catch (error) {
          console.error('日志系统关闭失败:', error);
        }
        console.log('\n收到终止信号，正在清理...');
        process.exit(0);
      }, 100);
    } catch {
      console.log('\n收到终止信号，正在清理...');
      process.exit(0);
    }
  });
}